﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using Home.Haushalt.Lib;
using Home.Haushalt.Lib.Element;
using Infragistics.Win;
using Infragistics.Win.UltraWinGrid;
using Infragistics.Win.UltraWinTabControl;

namespace Home.Haushalt.Gui
{
    /// <summary>
    /// 
    /// </summary>
    public partial class FrmProperty : Form
    {
        /// <summary></summary>
        public event EventHandler<HEventArgs> OnChanged;

        /// <summary></summary>
        protected ElementBase _elementObject;

        /// <summary></summary>
        public ElementBase ElementObject
        {
            get { return _elementObject; }
            set { _elementObject = value; }
        }

        /// <summary></summary>
        internal bool SingleSelection { get { return _selectedRows.Count.Equals(1); } }

        /// <summary></summary>
        protected List<DataRow> _selectedRows;

        DataSet verlaufDS = new DataSet();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="rows"></param>
        /// <returns></returns>
        public static FrmProperty Instantiate(List<DataRow> rows)
        {
            if (rows.Count.Equals(1))
            {
                //ChangeBackup cb = new ChangeBackup(rows[0]);
                //DAO.Tables[typeof(ChangeBackup)].Rows.Add(rows[0].Copy(DAO.Tables[typeof(ChangeBackup)]));
                //DAO.Save();
            }

            FrmProperty frmProperty = null;

            DataRow firstRow = rows[0];

            string elementTypeName = firstRow.Table.TableName;

            Type formType = Type.GetType("Home.Haushalt.Gui.FrmProperty" + elementTypeName);

            if (formType != null)
            {
                frmProperty = (FrmProperty)Activator.CreateInstance(formType);

                if (frmProperty != null)
                {
                    frmProperty.Init(rows);
                }
            }
            else if (firstRow.Table.Rows.IndexOf(firstRow).Equals(-1))
            {
                if (firstRow.Table.Columns.Contains(Date.Fields.Id))
                {
                    firstRow[Date.Fields.Id] = firstRow.Table.Compute("max(" + Date.Fields.Id + ")", string.Empty).ToInt() + 1;
                }

                firstRow.Table.Rows.Add(firstRow);
            }

            return frmProperty;
        }

        /// <summary>
        /// 
        /// </summary>
        public FrmProperty()
        {
            InitializeComponent();

            this.Shown += new EventHandler(FrmProperty_Shown);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="row"></param>
        protected virtual void Init(DataRow row)
        {
            Init(new DataRow[] { row }.ToList());
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="rows"></param>
        protected virtual void Init(List<DataRow> rows)
        {
            _selectedRows = rows;

            DataRow row = _selectedRows[0];

            if (!SingleSelection)
            {
                row = _selectedRows[0].Table.NewRow();

                foreach (DataColumn col in row.Table.Columns)
                {
                    if (col.DataType != typeof(bool))
                    {
                        row[col] = DBNull.Value;
                    }
                }
            }

            _elementObject = ElementBase.Instantiate(row, rows);


            // DAO.SaveToChangeBackup(_elementObject);


            _elementObject.OnPropertyChanged += new EventHandler<HEventArgs>(_elementObject_OnPropertyChanged);

            if (row.Table.Columns.Contains(ElementBase.ELEMENTPROPERTY_NOTE))
            {
                AddBinding(txtDesc.DataBindings, "Text", ElementBase.ELEMENTPROPERTY_NOTE);
            }

            if (SingleSelection && row.Table.Columns.Contains(ElementBase.ELEMENTPROPERTY_LABEL))
            {
                lstLabel.DataBindAtColumn(_elementObject.GetType(), ElementBase.ELEMENTPROPERTY_LABEL);
                AddBinding(lstLabel.DataBindings, "Value", ElementBase.ELEMENTPROPERTY_LABEL);
            }

            WindowController.Register(this);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _elementObject_OnPropertyChanged(object sender, HEventArgs e)
        {
            SetAppState();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void FrmProperty_Shown(object sender, EventArgs e)
        {
            lstLabel.DropDownStyle = UltraComboStyle.DropDown;

            if (!LayoutController.IsInDesignMode(this))
            {
                this.Text = LO.Common("FrmPropertyCaption", LO.ElementName(_elementObject.GetType()), _elementObject.PropertyFormCaption);

                SetTabCaption();

                SetAppState();
            }
        }

        #region SUBELEMENT TAB SUPPORT

        /// <summary>
        /// 
        /// </summary>
        private class SubElementTabSet
        {
            /// <summary></summary>
            public UcGridForm GridForm;
            /// <summary></summary>
            public Type ElementType;
            /// <summary></summary>
            public string ForeignIdName;
            /// <summary></summary>
            public object ForeignId;
            /// <summary></summary>
            public int SerieId;
            /// <summary></summary>
            public bool Initialized = false;

            /// <summary>
            /// 
            /// </summary>
            /// <param name="gridForm"></param>
            /// <param name="elementType"></param>
            /// <param name="foreignIdName"></param>
            /// <param name="foreignId"></param>
            /// <param name="serieId"></param>
            public SubElementTabSet(UcGridForm gridForm, Type elementType, string foreignIdName, object foreignId, int serieId)
            {
                GridForm = gridForm;
                ElementType = elementType;
                ForeignIdName = foreignIdName;
                ForeignId = foreignId;
                SerieId = serieId;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private void SetTabCaption()
        {
            foreach (UltraTab tab in this.tabControl.Tabs)
            {
                SubElementTabSet tabSet = tab.TabPage.Tag as SubElementTabSet;
                if (tabSet != null)
                {
                    int elementCount = DAO.GetSubRows(tabSet.ElementType, tabSet.ForeignIdName, tabSet.ForeignId).Length;

                    if (tabSet.SerieId < 0)
                    {
                        tab.Text = string.Format("{0} ({1})", LO.ElementList(tabSet.ElementType), elementCount);
                    }
                    else
                    {
                        int serieElementCount = elementCount;

                        List<int> postenIds = GetSeriePostenIDs(tabSet.SerieId);
                        if (postenIds.Count > 1)
                        {
                            string postenIdsStatement = "";
                            foreach (int postenId in postenIds)
                                postenIdsStatement += postenId.ToString() + ", ";

                            postenIdsStatement = postenIdsStatement.Substring(0, postenIdsStatement.Length - 2);

                            serieElementCount = DAO.GetRows(tabSet.ElementType, "{0} in ({1})", tabSet.ForeignIdName, postenIdsStatement).Length;
                        }

                        tab.Text = string.Format("{0} ({1}/{2})", LO.ElementList(tabSet.ElementType), elementCount, serieElementCount);
                    }

                    tab.Enabled = !_elementObject.IsNew;
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="serieId"></param>
        /// <returns></returns>
        private List<int> GetSeriePostenIDs(int serieId)
        {
            List<int> result = new List<int>();

            DataRow[] postenRows = DAO.GetSubRows(Posten.ElementType, Posten.Fields.SerieId, serieId);

            foreach (DataRow row in postenRows)
            {
                result.Add(row[Posten.Fields.Id].ToInt());
            }

            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="elementType"></param>
        /// <param name="foreignIdName"></param>
        /// <param name="foreignId"></param>
        /// <returns></returns>
        protected UltraTab AddTab(Type elementType, string foreignIdName, object foreignId)
        {
            return AddTab(elementType, foreignIdName, foreignId, -2);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="elementType"></param>
        /// <param name="foreignIdName"></param>
        /// <param name="foreignId"></param>
        /// <param name="serieId"></param>
        /// <returns></returns>
        protected UltraTab AddTab(Type elementType, string foreignIdName, object foreignId, int serieId)
        {
            UltraTab tab = new UltraTab();
            tab.Text = elementType.Name.ToString();
            this.tabControl.Tabs.Add(tab);

            UcGridForm ucGridForm = UcGridForm.Instatiate(elementType, DefaultColumnSets.TabDefault, DefaultColumnSets.TabDefault.ToString());
            ucGridForm.Load += new EventHandler(ucGridForm_Load);
            ucGridForm.BaseGrid.OnRefresh += new EventHandler<HEventArgs>(BaseGrid_OnRefresh);
            ucGridForm.Dock = DockStyle.Fill;
            ucGridForm.BaseGrid.ParentElement = _elementObject;
            tab.TabPage.Controls.Add(ucGridForm);

            Panel pnl = new Panel();
            pnl.Dock = DockStyle.Bottom;
            pnl.Height = 25;
            pnl.Visible = (serieId > -2);
            tab.TabPage.Controls.Add(pnl);

            HCheckBox rbAll = new HCheckBox();
            rbAll.AfterCheckStateChanged += new CheckEditor.AfterCheckStateChangedHandler(rbAll_AfterCheckStateChanged);
            rbAll.Location = new Point(10, 5);
            rbAll.Text = "alle in der Serie";
            rbAll.CheckAlign = ContentAlignment.MiddleLeft;
            rbAll.Appearance.TextHAlign = HAlign.Left;
            rbAll.Enabled = (serieId > -1);
            rbAll.Checked = false;

            pnl.Controls.Add(rbAll);

            SubElementTabSet tabSet = new SubElementTabSet(ucGridForm, elementType, foreignIdName, foreignId, serieId);
            tab.TabPage.Tag = tabSet;
            rbAll.Tag = tabSet;
            ucGridForm.Tag = tabSet;

            return tab;
        }

        void BaseGrid_OnRefresh(object sender, HEventArgs e)
        {
            SetTabCaption();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ucGridForm_Load(object sender, EventArgs e)
        {
            SubElementTabSet tabSet = ((UcGridForm)sender).Tag as SubElementTabSet;
            if (tabSet != null)
            {
                BindFilterConditions(tabSet, false);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rbAll_AfterCheckStateChanged(object sender, EventArgs e)
        {
            HCheckBox rbAll = (HCheckBox)sender;
            SubElementTabSet tabSet = rbAll.Tag as SubElementTabSet;

            BindFilterConditions(tabSet, rbAll.Checked);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="tabSet"></param>
        /// <param name="showAllInSerie"></param>
        private void BindFilterConditions(SubElementTabSet tabSet, bool showAllInSerie)
        {
            //Alle Filterconditions fürs layout löschen
            foreach (ColumnFilter filter in tabSet.GridForm.BaseGrid.DisplayLayout.Bands[0].ColumnFilters)
            {
                filter.FilterConditions.Clear();
            }

            //Alle Filters für die Felder finden, die mit gleicher Buchstabe anfangen
            List<ColumnFilter> setFilterList = tabSet.GridForm.BaseGrid.DisplayLayout.Bands[0].ColumnFilters.Cast<ColumnFilter>().Where(item => item.Column.Key.StartsWith(tabSet.ForeignIdName, StringComparison.OrdinalIgnoreCase)).ToList();
            tabSet.GridForm.BaseGrid.DisplayLayout.Bands[0].ColumnFilters.LogicalOperator = FilterLogicalOperator.Or;

            //Filter setzen
            //ColumnFilter setFilter = tabSet.GridForm.BaseGrid.DisplayLayout.Bands[0].ColumnFilters[tabSet.ForeignIdName];

            foreach (ColumnFilter setFilter in setFilterList)
            {
                if (showAllInSerie)
                {
                    setFilter.LogicalOperator = FilterLogicalOperator.Or;

                    List<int> postenIds = GetSeriePostenIDs(tabSet.SerieId);
                    foreach (int postenId in postenIds)
                    {
                        setFilter.FilterConditions.Add(FilterComparisionOperator.Equals, postenId);
                    }
                }
                else
                {
                    setFilter.FilterConditions.Add(FilterComparisionOperator.Equals, tabSet.ForeignId);
                }
            }

        }

        #endregion SUBELEMENT TAB SUPPORT

        /// <summary>
        /// 
        /// </summary>
        protected void Delete()
        {
            _elementObject.Delete();
        }

        /// <summary>
        /// 
        /// </summary>
        protected void SetAppState()
        {
            bool valueChanged = true;

            if (SingleSelection)
            {
                valueChanged = _elementObject.ValueChanged();
            }

            btnOk.Enabled = valueChanged;
            btnCancel.Text = (valueChanged && _selectedRows.Count.Equals(1)) ? "Verwerfen" : "Schließen";
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ctrl"></param>
        /// <param name="propertyName"></param>
        /// <param name="dataMember"></param>
        protected void AddBinding(ControlBindingsCollection bindcollection, string propertyName, string dataMember)
        {
            bindcollection.Add(propertyName, _elementObject.BindingTable, dataMember, false, DataSourceUpdateMode.OnPropertyChanged);
        }

        /// <summary>
        /// 
        /// </summary>
        protected void DataBind()
        {
            CurrencyManager cm = (CurrencyManager)this.BindingContext[_elementObject.BindingTable];
            cm.Position = 0;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnOk_Click(object sender, EventArgs e)
        {
            this.Enabled = false;
            Application.DoEvents();

            _elementObject.AcceptChanges(true);

            SetTabCaption();
            SetAppState();

            if (OnChanged != null)
                OnChanged(_elementObject, new HEventArgs("Element ist verändert"));

            this.Enabled = true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnCancel_Click(object sender, EventArgs e)
        {
            if (btnOk.Enabled && _selectedRows.Count.Equals(1))
            {
                OnCanceling();

                _elementObject.RejectChanges(true);

            }
            else
            {
                Close();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        protected virtual void OnCanceling()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmProperty_FormClosing(object sender, FormClosingEventArgs e)
        {
            _elementObject.RejectChanges(true);

            WindowController.Unregister(this);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmProperty_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Control && e.KeyCode.Equals(Keys.S))
            {
                btnOk_Click(sender, null);
            }
        }

    }
}
